home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / machine / bosco.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  12KB  |  636 lines

  1. /***************************************************************************
  2.  
  3.   machine.c
  4.  
  5.   Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
  6.   I/O ports)
  7.  
  8. Bosconian scoring info
  9.  
  10. I/O controller command 64h update score values: (set by game code)
  11.  
  12. 60h = switch to player 1
  13. 68h = switch to player 2
  14.  
  15. 81h =   10  Asteroid
  16. 83h =   20  Cosmo-Mine
  17. 87h =   50  I-Type
  18. 88h =   60  P-Type
  19. 89h =   70  E-Type
  20. 8Dh =  200  Spy Ship
  21. 93h =  200  Bonus
  22. 95h =  300  Bonus
  23. 96h =  400  Bonus
  24. 98h =  600  Bonus
  25. 9Ah =  800  Bonus
  26. A0h =  500  I-Type Formation
  27. A1h = 1000  P-Type Formation
  28. A2h = 1500  E-Type Formation
  29. A3h = 2000  Bonus
  30. A5h = 3000  Bonus
  31. A6h = 4000  Bonus
  32. A7h = 5000  Bonus
  33. A8h = 6000  Bonus
  34. A9h = 7000  Bonus
  35. B7h =  100  I-Type Leader
  36. B8h =  120  P-Type Leader
  37. B9h =  140  E-Type Leader
  38.  
  39. Bonuses are given at the end of a round if the game is set to auto
  40. difficulty and the round is completed on one life. Bonus values are:
  41.  
  42.  100x3  95h
  43.  100x4  96h
  44.  100x8  9Ah
  45.  200x4  96h,96h
  46.  200x8  9Ah,9Ah
  47.  300x8  A3h,96h
  48.  400x8  A5h,93h
  49.  500x8  A3h,A3h
  50.  600x8  A6h,9Ah
  51.  700x8  A7h,98h
  52.  800x8  A8h,96h
  53.  900x8  A9h,93h
  54. 1000x8  A6h,A6h
  55.  
  56.  
  57. I/O controller command 84h set bonus values: (set by game code)
  58.  
  59. Byte 0: always 10h
  60. Byte 1: indicator (20h=first bonus, 30h=interval bonus, others=unknown)
  61. Byte 2: BCD score (--ss----)
  62. Byte 3: BCD score (----ss--)
  63. Byte 4: BCD score (------ss)
  64.  
  65. Indicator values 20h and 30h are sent once during startup based upon
  66. the dip switch settings, other values are sent during gameplay.
  67. The default bonus setting is 20000, 70000, and every 70000.
  68.  
  69.  
  70. I/O controller command 94h read score returned value: (read by game code)
  71.  
  72. Byte 0: BCD score (fs------) and flags
  73. Byte 1: BCD score (--ss----)
  74. Byte 2: BCD score (----ss--)
  75. Byte 3: BCD score (------ss)
  76.  
  77. Flags: 80h=high score, 40h=first bonus, 20h=interval bonus
  78.  
  79.  
  80. Scores should be reset to 0 on I/O controller command C1h.
  81.  
  82. ***************************************************************************/
  83.  
  84. #include "driver.h"
  85. #include "cpu/z80/z80.h"
  86.  
  87.  
  88. unsigned char *bosco_sharedram;
  89. static unsigned char interrupt_enable_1,interrupt_enable_2,interrupt_enable_3;
  90. static int        HiScore;
  91. int        Score,Score1,Score2;
  92. int        NextBonus,NextBonus1,NextBonus2;
  93. int        FirstBonus,IntervalBonus;
  94.  
  95. static int credits;
  96.  
  97. void bosco_sample_play(int, int);
  98. void bosco_vh_interrupt(void);
  99.  
  100. static void *nmi_timer_1, *nmi_timer_2;
  101.  
  102. WRITE_HANDLER( bosco_halt_w );
  103.  
  104. void bosco_init_machine(void)
  105. {
  106.     credits = 0;
  107.     HiScore = 20000;
  108.     nmi_timer_1 = nmi_timer_2 = 0;
  109.     bosco_halt_w (0, 0);
  110.  
  111.     memory_region(REGION_CPU1)[0x8c00] = 1;
  112.     memory_region(REGION_CPU1)[0x8c01] = 1;
  113. }
  114.  
  115.  
  116. READ_HANDLER( bosco_sharedram_r )
  117. {
  118.     return bosco_sharedram[offset];
  119. }
  120.  
  121.  
  122.  
  123. WRITE_HANDLER( bosco_sharedram_w )
  124. {
  125.     bosco_sharedram[offset] = data;
  126. }
  127.  
  128.  
  129.  
  130. READ_HANDLER( bosco_dsw_r )
  131. {
  132.     int bit0,bit1;
  133.  
  134.  
  135.     bit0 = (input_port_0_r(0) >> offset) & 1;
  136.     bit1 = (input_port_1_r(0) >> offset) & 1;
  137.  
  138.     return bit0 | (bit1 << 1);
  139. }
  140.  
  141.  
  142.  
  143. /***************************************************************************
  144.  
  145.  Emulate the custom IO chip.
  146.  
  147. ***************************************************************************/
  148. static int customio_command_1;
  149. static unsigned char customio_1[16];
  150. static int mode;
  151.  
  152.  
  153. WRITE_HANDLER( bosco_customio_data_1_w )
  154. {
  155.     customio_1[offset] = data;
  156.  
  157. logerror("%04x: custom IO 1 offset %02x data %02x\n",cpu_get_pc(),offset,data);
  158.  
  159.     switch (customio_command_1)
  160.     {
  161.         case 0x48:
  162.             if (offset == 1)
  163.             {
  164.                 switch(customio_1[0])
  165.                 {
  166.                     case 0x20:     //        Mid Bang
  167.                         sample_start (0, 0, 0);
  168.                         break;
  169.                     case 0x10:     //        Big Bang
  170.                         sample_start (1, 1, 0);
  171.                         break;
  172.                     case 0x50:     //        Shot
  173.                         sample_start (2, 2, 0);
  174.                         break;
  175.                 }
  176.             }
  177.             break;
  178.  
  179.         case 0x64:
  180.             if (offset == 0)
  181.             {
  182.                 switch(customio_1[0])
  183.                 {
  184.                     case 0x60:    /* 1P Score */
  185.                         Score2 = Score;
  186.                         Score = Score1;
  187.                         NextBonus2 = NextBonus;
  188.                         NextBonus = NextBonus1;
  189.                         break;
  190.                     case 0x68:    /* 2P Score */
  191.                         Score1 = Score;
  192.                         Score = Score2;
  193.                         NextBonus1 = NextBonus;
  194.                         NextBonus = NextBonus2;
  195.                         break;
  196.                     case 0x81:
  197.                         Score += 10;
  198.                         break;
  199.                     case 0x83:
  200.                         Score += 20;
  201.                         break;
  202.                     case 0x87:
  203.                         Score += 50;
  204.                         break;
  205.                     case 0x88:
  206.                         Score += 60;
  207.                         break;
  208.                     case 0x89:
  209.                         Score += 70;
  210.                         break;
  211.                     case 0x8D:
  212.                         Score += 200;
  213.                         break;
  214.                     case 0x93:
  215.                         Score += 200;
  216.                         break;
  217.                     case 0x95:
  218.                         Score += 300;
  219.                         break;
  220.                     case 0x96:
  221.                         Score += 400;
  222.                         break;
  223.                     case 0x98:
  224.                         Score += 600;
  225.                         break;
  226.                     case 0x9A:
  227.                         Score += 800;
  228.                         break;
  229.                     case 0xA0:
  230.                         Score += 500;
  231.                         break;
  232.                     case 0xA1:
  233.                         Score += 1000;
  234.                         break;
  235.                     case 0xA2:
  236.                         Score += 1500;
  237.                         break;
  238.                     case 0xA3:
  239.                         Score += 2000;
  240.                         break;
  241.                     case 0xA5:
  242.                         Score += 3000;
  243.                         break;
  244.                     case 0xA6:
  245.                         Score += 4000;
  246.                         break;
  247.                     case 0xA7:
  248.                         Score += 5000;
  249.                         break;
  250.                     case 0xA8:
  251.                         Score += 6000;
  252.                         break;
  253.                     case 0xA9:
  254.                         Score += 7000;
  255.                         break;
  256.                     case 0xB7:
  257.                         Score += 100;
  258.                         break;
  259.                     case 0xB8:
  260.                         Score += 120;
  261.                         break;
  262.                     case 0xB9:
  263.                         Score += 140;
  264.                         break;
  265.                     default:
  266.                         logerror("unknown score: %02x\n",customio_1[0]);
  267.                     break;
  268.                 }
  269.             }
  270.             break;
  271.         case 0x84:
  272.             if (offset == 2)
  273.             {
  274.                 int hi = (data / 16);
  275.                 int mid = (data % 16);
  276.                 if (customio_1[1] == 0x20)
  277.                     FirstBonus = (hi * 100000) + (mid * 10000);
  278.                 if (customio_1[1] == 0x30)
  279.                     IntervalBonus = (hi * 100000) + (mid * 10000);
  280.             }
  281.             else if (offset == 3)
  282.             {
  283.                 int lo = (data / 16);
  284.                 if (customio_1[1] == 0x20)
  285.                     FirstBonus = FirstBonus + (lo * 1000);
  286.                 if (customio_1[1] == 0x30)
  287.                     IntervalBonus = IntervalBonus + (lo * 1000);
  288.             }
  289.             break;
  290.     }
  291. }
  292.  
  293.  
  294. READ_HANDLER( bosco_customio_data_1_r )
  295. {
  296.     switch (customio_command_1)
  297.     {
  298.         case 0x71:
  299.             if (offset == 0)
  300.             {
  301.                 int p4 = readinputport (4);
  302.  
  303.                 /* check if the user inserted a coin */
  304.                 if ((p4 & 0x10) == 0 && credits < 99)
  305.                     credits++;
  306.  
  307.                 /* check if the user inserted a coin */
  308.                 if ((p4 & 0x20) == 0 && credits < 99)
  309.                     credits++;
  310.  
  311.                 /* check if the user inserted a coin */
  312.                 if ((p4 & 0x40) == 0 && credits < 99)
  313.                     credits++;
  314.  
  315.                 /* check for 1 player start button */
  316.                 if ((p4 & 0x04) == 0 && credits >= 1)
  317.                     credits--;
  318.  
  319.                 /* check for 2 players start button */
  320.                 if ((p4 & 0x08) == 0 && credits >= 2)
  321.                     credits -= 2;
  322.  
  323.                 if (mode)    /* switch mode */
  324.                     return (p4 & 0x80);
  325.                 else    /* credits mode: return number of credits in BCD format */
  326.                     return (credits / 10) * 16 + credits % 10;
  327.             }
  328.             else if (offset == 1)
  329.             {
  330.                 int in = readinputport(2), dir;
  331.  
  332.             /*
  333.                   Direction is returned as shown below:
  334.                                 0
  335.                             7        1
  336.                         6                2
  337.                             5        3
  338.                                 4
  339.                   For the previous direction return 8.
  340.              */
  341.                 dir = 8;
  342.                 if ((in & 0x01) == 0)        /* up */
  343.                 {
  344.                     if ((in & 0x02) == 0)    /* right */
  345.                         dir = 1;
  346.                     else if ((in & 0x08) == 0) /* left */
  347.                         dir = 7;
  348.                     else
  349.                         dir = 0;
  350.                 }
  351.                 else if ((in & 0x04) == 0)    /* down */
  352.                 {
  353.                     if ((in & 0x02) == 0)    /* right */
  354.                         dir = 3;
  355.                     else if ((in & 0x08) == 0) /* left */
  356.                         dir = 5;
  357.                     else
  358.                         dir = 4;
  359.                 }
  360.                 else if ((in & 0x02) == 0)    /* right */
  361.                     dir = 2;
  362.                 else if ((in & 0x08) == 0) /* left */
  363.                     dir = 6;
  364.  
  365.                 /* check fire (both impulse and hold, boscomd2 has autofire) */
  366.                 dir |= (in & 0x30);
  367.  
  368.                 return dir;
  369.             }
  370.             break;
  371.  
  372.         case 0x94:
  373.             if (offset == 0)
  374.             {
  375.                 int flags = 0;
  376.                 int lo = (Score / 1000000) % 10;
  377.                 if (Score >= HiScore)
  378.                 {
  379.                     HiScore = Score;
  380.                     flags |= 0x80;
  381.                 }
  382.                 if (Score >= NextBonus)
  383.                 {
  384.                     if (NextBonus == FirstBonus)
  385.                     {
  386.                         NextBonus = IntervalBonus;
  387.                         flags |= 0x40;
  388.                     }
  389.                     else
  390.                     {
  391.                         NextBonus += IntervalBonus;
  392.                         flags |= 0x20;
  393.                     }
  394.                 }
  395.                 return lo | flags;
  396.             }
  397.             else if (offset == 1)
  398.             {
  399.                 int hi = (Score / 100000) % 10;
  400.                 int lo = (Score / 10000) % 10;
  401.                 return (hi * 16) + lo;
  402.             }
  403.             else if (offset == 2)
  404.             {
  405.                 int hi = (Score / 1000) % 10;
  406.                 int lo = (Score / 100) % 10;
  407.                 return (hi * 16) + lo;
  408.             }
  409.  
  410.             else if (offset == 3)
  411.             {
  412.                 int hi = (Score / 10) % 10;
  413.                 int lo = Score % 10;
  414.                 return (hi * 16) + lo;
  415.             }
  416.             break;
  417.  
  418.         case 0x91:
  419.             if (offset <= 2)
  420.                 return 0;
  421.             break;
  422.     }
  423.  
  424.     return -1;
  425. }
  426.  
  427.  
  428. READ_HANDLER( bosco_customio_1_r )
  429. {
  430.     return customio_command_1;
  431. }
  432.  
  433. void bosco_nmi_generate_1 (int param)
  434. {
  435.     cpu_cause_interrupt (0, Z80_NMI_INT );
  436. }
  437.  
  438. WRITE_HANDLER( bosco_customio_1_w )
  439. {
  440.     if (data != 0x10)
  441.         logerror("%04x: custom IO 1 command %02x\n",cpu_get_pc(),data);
  442.  
  443.     customio_command_1 = data;
  444.  
  445.     switch (data)
  446.     {
  447.         case 0x10:
  448.             if (nmi_timer_1) timer_remove (nmi_timer_1);
  449.             nmi_timer_1 = 0;
  450.             return;
  451.  
  452.         case 0x61:
  453.             mode = 1;
  454.             break;
  455.  
  456.         case 0xC1:
  457.             Score = 0;
  458.             Score1 = 0;
  459.             Score2 = 0;
  460.             NextBonus = FirstBonus;
  461.             NextBonus1 = FirstBonus;
  462.             NextBonus2 = FirstBonus;
  463.             break;
  464.  
  465.         case 0xC8:
  466.             break;
  467.  
  468.         case 0x84:
  469.             break;
  470.  
  471.         case 0x91:
  472.             mode = 0;
  473.             break;
  474.  
  475.         case 0xa1:
  476.             mode = 1;
  477.             break;
  478.     }
  479.  
  480.     nmi_timer_1 = timer_pulse (TIME_IN_USEC (50), 0, bosco_nmi_generate_1);
  481. }
  482.  
  483.  
  484.  
  485. /***************************************************************************
  486.  
  487.  Emulate the second (!) custom IO chip.
  488.  
  489. ***************************************************************************/
  490. static int customio_command_2;
  491. static unsigned char customio_2[16];
  492.  
  493. WRITE_HANDLER( bosco_customio_data_2_w )
  494. {
  495.     customio_2[offset] = data;
  496.  
  497. logerror("%04x: custom IO 2 offset %02x data %02x\n",cpu_get_pc(),offset,data);
  498.     switch (customio_command_2)
  499.     {
  500.         case 0x82:
  501.             if (offset == 2)
  502.             {
  503.                 switch(customio_2[0])
  504.                 {
  505.                     case 1: // Blast Off
  506.                         bosco_sample_play(0x0020 * 2, 0x08D7 * 2);
  507.                         break;
  508.                     case 2: // Alert, Alert
  509.                         bosco_sample_play(0x8F7 * 2, 0x0906 * 2);
  510.                         break;
  511.                     case 3: // Battle Station
  512.                         bosco_sample_play(0x11FD * 2, 0x07DD * 2);
  513.                         break;
  514.                     case 4: // Spy Ship Sighted
  515.                         bosco_sample_play(0x19DA * 2, 0x07DE * 2);
  516.                         break;
  517.                     case 5: // Condition Red
  518.                         bosco_sample_play(0x21B8 * 2, 0x079F * 2);
  519.                         break;
  520.                 }
  521.             }
  522.             break;
  523.     }
  524. }
  525.  
  526.  
  527. READ_HANDLER( bosco_customio_data_2_r )
  528. {
  529.     switch (customio_command_2)
  530.     {
  531.         case 0x91:
  532.             if (offset == 2)
  533.                 return cpu_readmem16(0x89cc);
  534.             else if (offset <= 3)
  535.                 return 0;
  536.             break;
  537.     }
  538.  
  539.     return -1;
  540. }
  541.  
  542.  
  543. READ_HANDLER( bosco_customio_2_r )
  544. {
  545.     return customio_command_2;
  546. }
  547.  
  548. void bosco_nmi_generate_2 (int param)
  549. {
  550.     cpu_cause_interrupt (1, Z80_NMI_INT);
  551. }
  552.  
  553. WRITE_HANDLER( bosco_customio_2_w )
  554. {
  555.     if (data != 0x10)
  556.         logerror("%04x: custom IO 2 command %02x\n",cpu_get_pc(),data);
  557.  
  558.     customio_command_2 = data;
  559.  
  560.     switch (data)
  561.     {
  562.         case 0x10:
  563.             if (nmi_timer_2) timer_remove (nmi_timer_2);
  564.             nmi_timer_2 = 0;
  565.             return;
  566.     }
  567.  
  568.     nmi_timer_2 = timer_pulse (TIME_IN_USEC (50), 0, bosco_nmi_generate_2);
  569. }
  570.  
  571.  
  572.  
  573.  
  574.  
  575.  
  576. WRITE_HANDLER( bosco_halt_w )
  577. {
  578.     if (data & 1)
  579.     {
  580.         cpu_set_reset_line(1,CLEAR_LINE);
  581.         cpu_set_reset_line(2,CLEAR_LINE);
  582.     }
  583.     else
  584.     {
  585.         cpu_set_reset_line(1,ASSERT_LINE);
  586.         cpu_set_reset_line(2,ASSERT_LINE);
  587.     }
  588. }
  589.  
  590.  
  591.  
  592. WRITE_HANDLER( bosco_interrupt_enable_1_w )
  593. {
  594.     interrupt_enable_1 = (data&1);
  595. }
  596.  
  597.  
  598.  
  599. int bosco_interrupt_1(void)
  600. {
  601.     bosco_vh_interrupt();    /* update the background stars position */
  602.  
  603.     if (interrupt_enable_1) return interrupt();
  604.     else return ignore_interrupt();
  605. }
  606.  
  607.  
  608.  
  609. WRITE_HANDLER( bosco_interrupt_enable_2_w )
  610. {
  611.     interrupt_enable_2 = data & 1;
  612. }
  613.  
  614.  
  615.  
  616. int bosco_interrupt_2(void)
  617. {
  618.     if (interrupt_enable_2) return interrupt();
  619.     else return ignore_interrupt();
  620. }
  621.  
  622.  
  623.  
  624. WRITE_HANDLER( bosco_interrupt_enable_3_w )
  625. {
  626.     interrupt_enable_3 = !(data & 1);
  627. }
  628.  
  629.  
  630.  
  631. int bosco_interrupt_3(void)
  632. {
  633.     if (interrupt_enable_3) return nmi_interrupt();
  634.     else return ignore_interrupt();
  635. }
  636.